﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Dimok;
/*
using System.Windows.Interactivity;
 * 
 */
namespace DataGridWithFilter {

	#region BorderBehavior ======================
	public class BorderBehavior : Behavior<Border> {
		Storyboard storyboard;
		ColorAnimation animation;
		DoubleAnimation animationOpacity;
		Color originalColor;
		double origonalOpacity;

		public static readonly DependencyProperty InactiveTransparencyProperty = DependencyProperty.Register("InactiveTransparency", typeof(double), typeof(BorderBehavior), new PropertyMetadata(0.5));
		public double InactiveTransparency {
			get { return (double)GetValue(InactiveTransparencyProperty); }
			set { SetValue(InactiveTransparencyProperty, value); }
		}


		public Color InteractiveColor {
			get { return (Color)GetValue(InteractiveColorProperty); }
			set { SetValue(InteractiveColorProperty, value); }
		}
		public static readonly DependencyProperty InteractiveColorProperty =
				DependencyProperty.Register("InteractiveColor", typeof(Color), typeof(BorderBehavior), new PropertyMetadata(Colors.Transparent));



		public static readonly DependencyProperty DurationProperty = DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(BorderBehavior), new PropertyMetadata(TimeSpan.FromSeconds(0.2)));
		public TimeSpan Duration {
			get { return (TimeSpan)GetValue(DurationProperty); }
			set { SetValue(DurationProperty, value); }
		}

		protected override void OnAttached() {
			base.OnAttached();

			storyboard = new Storyboard();

			animation = new ColorAnimation();
			animation.Duration = Duration;
			Storyboard.SetTarget(animation, AssociatedObject);
			Storyboard.SetTargetProperty(animation, new PropertyPath("(Border.BorderBrush).(SolidColorBrush.Color)"));
			storyboard.Children.Add(animation);

			animationOpacity = new DoubleAnimation();
			animationOpacity.Duration = Duration;
			Storyboard.SetTarget(animationOpacity, AssociatedObject);
			Storyboard.SetTargetProperty(animationOpacity, new PropertyPath(UIElement.OpacityProperty));
			storyboard.Children.Add(animationOpacity);

			if (AssociatedObject.BorderBrush == null)
				AssociatedObject.BorderBrush = new SolidColorBrush(Colors.Transparent);

			originalColor = (AssociatedObject.BorderBrush as SolidColorBrush).Color;
			origonalOpacity = AssociatedObject.Opacity;

			AssociatedObject.MouseEnter += OnMouseEnter;
			AssociatedObject.MouseLeave += OnMouseLeave;
		}

		protected override void OnDetaching() {
			base.OnDetaching();

			AssociatedObject.MouseEnter -= OnMouseEnter;
			AssociatedObject.MouseLeave -= OnMouseLeave;
		}

		void OnMouseLeave(object sender, MouseEventArgs e) {
			animation.To = originalColor;
			animationOpacity.To = origonalOpacity;
			storyboard.Begin();
		}

		void OnMouseEnter(object sender, MouseEventArgs e) {
			animation.To = InteractiveColor;
			animationOpacity.To = 1;
			storyboard.Begin();
		}
	}
	#endregion ==================================

	public class MoveCurrentToPositionBehavior : TriggerAction<UIElement> {
    private bool _enable = true;
    public bool Enable {
      get { return _enable; }
      set { _enable = value; }
    }
    protected override void Invoke(object parameter) {
      this.AssociatedObject.GetParent<DataGridWithFilter.DataGrid>().FilteredSource.CanMoveCurrentToPosition = Enable;
    }
  }
	public class SelfRegister : TriggerAction<UIElement> {
		private string _enable = "";
		public string UIElementName {
			get { return _enable; }
			set { _enable = value; }
		}
		protected override void Invoke(object parameter) {
			var dg = this.AssociatedObject.GetParent<DataGridWithFilter.DataGrid>();
			dg.SetProperty(UIElementName, this.AssociatedObject);
		}
	}
	public class VisibilityByModel : TriggerAction<FrameworkElement> {
		private string _propertyName = "";
		public string PropertyName {
			get { return _propertyName; }
			set { _propertyName = value; }
		}
		protected override void Invoke(object parameter) {
			var dc = this.AssociatedObject.GetParentDataContext<Model>();
			if (dc == null) return;
//			this.AssociatedObject.Visibility = dc.ShowFilter.HasValue && dc.ShowFilter.Value ? Visibility.Visible : Visibility.Collapsed;
			var b = new Binding(PropertyName) { Source = dc, Converter = new Dimok.Converters.VisibilityConverter() };
			AssociatedObject.SetBinding(UIElement.VisibilityProperty, b);
		}
	}
	public class BindToParent : TriggerAction<FrameworkElement> {
		private string _propertyName = "";
		public string PropertyName {
			get { return _propertyName; }
			set { _propertyName = value; }
		}
		protected override void Invoke(object parameter) {
			var dg = this.AssociatedObject.GetParent<DataGridWithFilter.DataGrid>();
			var dc = this.AssociatedObject.GetParentDataContext<ProfileModel>();
			if (dc == null) return;
			var b = new Binding(PropertyName) { Source = dc,Mode= BindingMode.TwoWay};
			var fe = this.AssociatedObject;
			DependencyProperty dp;
			if (AssociatedObject is CheckBox) dp = CheckBox.IsCheckedProperty;
			else if (AssociatedObject is TextBox) dp = TextBox.TextProperty;
			else throw new NotSupportedException("Control of type " + AssociatedObject.GetType().Name + " is not supported by BindToParent behavior.");
			fe.SetBinding(dp, b);
		}
	}

	public class ReBindToProfileModel : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var dc = this.AssociatedObject.GetParentDataContext<ProfileModel>();
			if (dc == null) return;
			this.AssociatedObject.DataContext = dc;
			return;
			var fields = this.AssociatedObject.GetType().GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
			foreach (var pi in fields.Where(f=>f.FieldType == typeof(DependencyProperty))) {
				var dp = pi.GetValue(this.AssociatedObject) as DependencyProperty;
				var be = this.AssociatedObject.GetBindingExpression(dp);
				var pb = be == null ? null : be.ParentBinding;
				if (pb == null || pb.ElementName + "" != "" || pb.RelativeSource != null) continue;
				var b = new Binding(pb.Path.Path) {
					Source = dc,
					Mode = pb.Mode,
					Converter = pb.Converter,
					ConverterParameter = pb.ConverterParameter,
					ConverterCulture = pb.ConverterCulture,
					BindsDirectlyToSource = pb.BindsDirectlyToSource,
					NotifyOnValidationError = pb.NotifyOnValidationError,
					UpdateSourceTrigger = pb.UpdateSourceTrigger,
					ValidatesOnExceptions = pb.ValidatesOnExceptions
				};
				this.AssociatedObject.SetBinding(dp, b);
			}
		}
	}

	public class BindToProfileModel : TriggerAction<FrameworkElement> {
		private string _propertyName = "";
		public string PropertyName {
			get { return _propertyName; }
			set { _propertyName = value; }
		}
		protected override void Invoke(object parameter) {
			var dc = this.AssociatedObject.GetParentDataContext<ProfileModel>();
			if (dc == null) return;
			var b = new Binding(PropertyName) { Source = dc, Mode = BindingMode.TwoWay };
			var fe = this.AssociatedObject;
			DependencyProperty dp;
			if (AssociatedObject is CheckBox) dp = CheckBox.IsCheckedProperty;
			else if (AssociatedObject is TextBox) dp = TextBox.TextProperty;
			else throw new NotSupportedException("Control of type " + AssociatedObject.GetType().Name + " is not supported by BindToParent behavior.");
			fe.SetBinding(dp, b);
		}
	}
	public class OpenRowMenu : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var dg = this.AssociatedObject.GetParent<DataGridWithFilter.DataGrid>();
			dg.ShowRowMenu(this.AssociatedObject);
		}
	}
	public class RemoveProfile : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var profileName = AssociatedObject.DataContext + "";
			var profileModel = ((Dimok.ProfileModel.ProfileSelection)(this.AssociatedObject.DataContext)).Model as ProfileModel;
			if (profileModel != null && MessageBox.Show("Remove " + profileName + " profile?", "Profile", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
				profileModel.RemoveProfile(AssociatedObject.DataContext + "");
		}
	}
	public class SaveProfile : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var profileName = AssociatedObject.DataContext + "";
			var profileModel = ((Dimok.ProfileModel.ProfileSelection)(this.AssociatedObject.DataContext)).Model as ProfileModel;
			if (profileModel != null && MessageBox.Show("Save " + profileName + " profile?", "Profile", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
				profileModel.SavePageLayoutAsync(AssociatedObject.DataContext + "");
		}
	}
	public class ResetLayout : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var dc = AssociatedObject.DataContext as ProfileModel;
			if (dc != null) dc.OnResetPageLayout();
			else System.Windows.Browser.HtmlPage.Window.Alert(AssociatedObject.GetType().Name + " has DataContext other then " + typeof(ProfileModel).Name);
		}
	}
	public class SaveLayout : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var dc = AssociatedObject.DataContext as ProfileModel;
			if (dc != null) dc.SavePageLayoutAsync(dc.ProfileName);
			else System.Windows.Browser.HtmlPage.Window.Alert(AssociatedObject.GetType().Name + " has DataContext other then " + typeof(ProfileModel).Name);
		}
	}
	public class ShowProfileListMenu : TriggerAction<FrameworkElement> {
		protected override void Invoke(object parameter) {
			var dg = this.AssociatedObject.GetParent<DataGridWithFilter.DataGrid>();
			var menu = Telerik.Windows.Controls.RadContextMenu.GetContextMenu(AssociatedObject);
			if (menu.DataContext == null) menu.DataContext = dg.DataContext;
			menu.IsOpen = true;
			//dg.ResetPageLayout();
		}
	}

}
